home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 22
/
Cream of the Crop 22.iso
/
program
/
cgazv4n2.zip
/
ANASTACK.C
next >
Wrap
C/C++ Source or Header
|
1989-08-17
|
7KB
|
267 lines
#include <stdio.h>
/******************************************************************
* Module: anastack.c
* Author: John Rex
* Compiler: MSC 5.1, TurboC 2.0
* Memory model: any
* Purpose: analyze and report on stack usage
*
* Usage: For use with MSC 5.1, getsp.asm must be assembled
* and linked in. Then,
*
* void start_anastack(), report_anastack();
*
* .. at beginning of code, in main():
* start_anastack();
*
* .. then, whenever desired:
* report_anastack("message");
*
* The first routine initializes some data areas and writes a unique byte
* into the stack area. The second routine then reports on this, labeling
* the report with the string passed to it.
*
* Compile switches:
* DEBUG - if == 1, compile a test driver
*
* Sources: This code was derived from study of the Turbo C and Microsoft
* C run-time libraries and startup code.
*
* Source code may be used freely if authorship is acknowledged.
* Object code may be used freely.
*************************************************************************/
#if defined(__TURBOC__)
#define TURBO
#if defined(__SMALL__) || defined(__MEDIUM__) || defined(__TINY__)
#define TURBOSMALL
#else
#define TURBOLARGE
#endif
#else
#define MSC
#endif
#define DEBUG 1
/* define our own pointer manipulation macros */
#define FP_OFF(x) ( (unsigned) x)
#define FP_SEG(x) ( (unsigned) ( ((long) x) >> 16) )
#define MK_FP(seg,off) ((char far *) ( (((long) seg) << 16) + off) )
/* the pattern we use in the stack */
#define PATTERN (char) 0xEF
#if defined(TURBO)
extern unsigned _stklen; /* stack length */
#else /* Microsoft C */
extern int end; /* the marker that locates the bottom of the stack */
unsigned getsp(); /* returns current value of SP, the stack pointer */
#endif
/* storage for stack's description */
static char far *stack_bottom;
static char far *stack_top;
/* initialize stack area */
void start_anastack()
{
char far *ptr;
#if defined(TURBO)
# if defined(TURBOSMALL)
extern char far *_heapbase; /* Points to beginning of the far heap.
* This location marks the true top of
* the stack.
*/
long bottom, ss_normal; /* for pointer conversions */
bottom = FP_SEG(_heapbase); /* true top of stack */
bottom <<= 4;
bottom -= _stklen; /* true bottom of stack */
/* now normalize bottom of stack to be SS relative */
ss_normal = ((long)_SS) << 4;
bottom -= ss_normal;
stack_bottom = MK_FP(_SS, ((unsigned) bottom) );
# else /* Turbo C Compact, Large, or Huge models */
stack_bottom = MK_FP(_SS,0); /* This is the simplest case, since in
* these models the stack has its own
* segment.
*/
# endif
stack_top = MK_FP(_SS, _SP); /* Top of usable stack */
#else /* Microsoft C */
stack_bottom = (char far *) &end; /* end is created by linker
at the bottom of the stack */
stack_top = MK_FP(FP_SEG(stack_bottom), getsp());
#endif
/* overwrite free stack area */
for (ptr = stack_bottom; ptr != stack_top; ptr++)
*ptr = PATTERN;
}
/* report on stack usage */
void report_anastack(char *message)
{
unsigned size, used, now_using;
char far *been_to, far *now_at;
int i=0;
/* compute a few things ... */
/* ... size of stack */
#if defined(TURBO)
# if defined(TURBOSMALL)
/* small/medium models--malloc() may actually steal some of the
* stack's area - must watch for this.
*/
extern unsigned __brklvl;
size = FP_OFF(stack_top) - __brklvl;
if (size > _stklen)
size = _stklen;
if (__brklvl > FP_OFF(stack_bottom))
/* malloc() has encroached on stack--must reset stack bottom */
stack_bottom = MK_FP(_SS, __brklvl);
# else
size = _stklen;
# endif
#else /* Microsoft C */
size = FP_OFF(stack_top) - FP_OFF(stack_bottom);
#endif
/* ... amount of stack used so far */
for (been_to = stack_bottom;
(*been_to == PATTERN) && (been_to != stack_top); been_to++, i++);
used = FP_OFF(stack_top) - FP_OFF(been_to);
/* ... where we are now */
#if defined(TURBO)
now_at = MK_FP(_SS, _SP);
#else
now_at = MK_FP(FP_SEG(stack_bottom), getsp());
#endif
now_using = FP_OFF(stack_top) - FP_OFF(now_at);
/* now print report */
printf("report_anastack(): %s\n", message);
printf(" The stack contains %u bytes and extends from %Fp to %Fp\n",
size, stack_bottom, stack_top);
printf(" The stack pointer is now at %Fp, using %u bytes (%d%%)\n",
now_at, now_using, (int) (100L * now_using / size));
printf(" The stack has been as low as %Fp, using %u bytes (%d%%)\n\n",
been_to, used, (int) (100L * used / size));
}
#pragma page()
#if DEBUG==1
#include <stdlib.h>
#include <string.h>
#if defined(TURBOSMALL)
char *mode;
/* a routine to use up the heap */
void tell_more()
{
extern unsigned __brklvl;
char *ptr;
int count;
printf("tell_more:\n");
printf(" __brklvl is %x\n",__brklvl);
count = 0;
while((ptr = malloc(1024)) != NULL) {
memset(ptr,'w',1024);
count++;
}
printf(" Able to allocate %d blocks of 1024 bytes\n", count);
printf(" __brklvl is %x\n\n",__brklvl);
}
#endif
/* a routine to use the stack */
void recurse(int i)
{
if (i == 0) {
report_anastack("recurse() called with zero");
#if defined(TURBOSMALL)
if (strchr(mode, 'r') != NULL)
tell_more();
#endif
}
else
recurse(i-1);
}
/*
* test driver to demonstrate behavior of stack. Usage:
*
* I. Microsoft C (all models)
* Turbo C (Compact, Large, Huge)
*
* Just invoke the .exe file. No command line options.
*
* II. Turbo C (Tiny, Small, Medium)
*
* anastack command
*
* where command may be
* (1) Empty (i.e., no string)
* or (2) A string containing any or all of the chars "ser".
* This string controls calls to tell_more, a routine that
* allocates 1024 byte blocks on the heap until there is no
* more room. The letters mean:
* 's' => call tell_more at start of main()
* 'e' => call tell_more at end of main()
* 'r' => call tell_more at bottom of recursive descent
* See the text for a discussion of what this demonstrates.
*/
void main(int argc, char **argv)
{
#if defined(TURBOSMALL)
mode = argv[1]; /* controls use of tell_more */
#endif
start_anastack();
#if defined(TURBOSMALL)
if (strchr(mode, 's') != NULL)
tell_more();
#endif
report_anastack("beginning of main()");
report_anastack("second call in a row to report_anastack()");
recurse(200);
#if defined(TURBOSMALL)
if (strchr(mode, 'e') != NULL)
tell_more();
#endif
report_anastack("at end of main()");
}
#endif